#include "../GatewayLoginManager/LightLoginManager.h"
#include "../../Lib/prpsock/prpsock.h"
#include "../../lib/sspsock/sspsock.h"

using namespace BAM;


//#define SLEEPING

int main(int argc, char ** argv)
{

  if (argc != 5)
  {
	  cout << "USAGE: \n" 
		  << "		client.exe relayaddress:port localaddress:port \n"
		  << "		client.exe relayaddress:port localport (for loopback connections \n";
		  return 0;
  }


char *b = argv[2];

BAM::cIPAddr *ip = 0;
do
{
	if (*b == ':')
	{
		ip = new BAM::cIPAddr(argv[2]);
		break;
	}
}
while(*b++);

if (!ip)
{
	if (strlen(argv[2])>5)
	{
		cout << "wrong port\n";
		return -1;
	}
	char buf[15];
	memcpy(buf, "127.0.0.1:", 10);
	memcpy(buf+10, argv[2], strlen(argv[2])+1);
	ip = new BAM::cIPAddr(buf);
	
}


  WSADATA wsaData;
  WSAStartup(MAKEWORD(2,2), &wsaData);

  
  SOCKET ConnectSocket;
  ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (ConnectSocket == INVALID_SOCKET) 
  {
    printf("Error at socket(): %ld\n", WSAGetLastError());
    WSACleanup();
    return -1;
  }

  sockaddr_in clientService; 
  clientService = ip->SockAddr();
  clientService.sin_family = AF_INET;

  if ( connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) 
  {
    printf( "Failed to connect.\n" );
    WSACleanup();
    return -1;
  }

	unsigned long one = 1;
	ioctlsocket(ConnectSocket, FIONBIO, &one);
	LightLoginManager lm(argv[3], argv[4]);

	BAM::cPrpSocket *Sock;
	BAM::cSSPSocket *SSP;
	try
	{
		Sock =  new BAM::cPrpSocket(0, &lm, BAM::cPacket((BAM::byte*)argv[3], strlen(argv[3])), lm.GetId(),	BAM::Prp_Socket_Server);
		Sock->connect(argv[1]);
		SSP = new BAM::cSSPSocket(Sock, &lm, BAM::cPacket((BAM::byte*)argv[3], strlen(argv[3])));
		SSP->shortinit(Sock);
		// lm, username, ipaddr?
	}

	catch (...)
	{
		cout << "Couldn't connect to " << argv[1] << endl;
		
		#ifdef SLEEPING
		Sleep(5000);
		#endif

		return -1;
	}

	
	char buf[10000];
	cPacket p;
	while(true)
	{
		try
		{
			Sleep(1);
			int res = ::recv(ConnectSocket, buf, 10000,0); /* *** */
			//int res = CRecvWrapper(&ConnectSocket, clientService, buf, 10000);
			if ( (res==-1) && (WSAGetLastError() != WSAEWOULDBLOCK) ) break;
			if (res == 0) break;
			if (res > 0) 
			{
				SSP->send(cPacket((BAM::byte*)buf, res)); /* *** */
				//if (CSSPSendWrapper(SSP, &lm, "user", buf, res) == -1)
				//	break;
			}

			bool bres;
			bres = (SSP->RecvEx(&p, false)); /* *** */
			//res = CSSPRecvWrapper(SSP, &lm, "user", &p);
			//if (res == -1) break;
			if (bres)
			{
				res = ::send(ConnectSocket, (char*)p.getData(), p.getLength(), 0); /* *** */
				//if (-1 == CSendWrapper(&ConnectSocket, clientService, (char*)p.getData(), p.getLength()))
				//	break;
				if (res == -1) break;
			}
		}
		catch(const BAM::SocketException &e)
		{
			cout << "Exception thrown: " << e.what();
			#ifdef SLEEPING
			Sleep(5000);
			#endif

			WSACleanup();
			return 0;
			break;
		}
	}


	cout << "Connection closed with winsock error " << WSAGetLastError() << endl;
	
	#ifdef SLEEPING
	Sleep(5000);
	#endif

	WSACleanup();
	return 0;	

}